package com.xaicode.learn.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;

/**
 * scattering: write data to buffer with multi buffer array in order
 * gathering: read data to buffer with multi buffer array in order
 *
 * @author Locker xaicode@sina.com
 * @version 1.0
 * @date 2021/6/13 0013 2:45
 */
@Slf4j
public class ScatteringAndGathering01 {

    public static void main(String[] args) throws IOException {

        // create internet socket
        final InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);
        // open server socket channel
        final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // bind internet socket to server socket channel
        serverSocketChannel.socket().bind(inetSocketAddress);

        // create buffer array
        // understand byte size and order
        final ByteBuffer[] byteBuffers = new ByteBuffer[2];
        byteBuffers[0] = ByteBuffer.allocate(5);
        byteBuffers[1] = ByteBuffer.allocate(5);

        // wait connect (such as telnet)
        final SocketChannel socketChannel = serverSocketChannel.accept();

        // test: max 8
        int testReadLength = 10;

        while (true) {
            // read
            int byteRead = 0;
            while (byteRead < testReadLength) {
                long read = socketChannel.read(byteBuffers);
                byteRead += read;
                log.info("byteRead = {}", byteRead);
                // print
                Arrays.asList(byteBuffers)
                        .forEach(buffer -> {
                            log.info("position={}, limit={}", buffer.position(), buffer.limit());
                        });
            }

            // flip each
            Arrays.asList(byteBuffers).forEach(Buffer::flip);

            // show back
            long byteWrite = 0;
            while (byteWrite < testReadLength) {
                long write = socketChannel.write(byteBuffers);
                byteWrite += write;
            }

            // clear each
            Arrays.asList(byteBuffers).forEach(Buffer::clear);

            log.info("byteRead={}, byteWrite={}, totalLength={}", byteRead, byteWrite, testReadLength);
        }

    }

}
